#ifndef __INKLUDE_C_UDP_BOOST_H__
#define __INKLUDE_C_UDP_BOOST_H__

#include <Inklude/Inklude.h>
#include <Inklude/ikCString.h>
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <memory>

using boost::asio::ip::tcp;

namespace Inklude
{

namespace Internal
{
    /*!
    * @brief This is for hiding specific implementation with boost.
    *        It contains forward declaration and include boost header files.
    *        Because all bools related calls done in here,
    *        End developer doesn't need to have boost lib even though the code use the boost in the inside.
    * @author Seokhwan Kim, IPLAB, Dept. of CS., Univ. of Tsukuba
    * @date Nov, 2011
    */ 
    class ikCTcpBoost
    {
    public:
        typedef std::shared_ptr<std::function<void (size_t)> > AsyncHandler;


        ikCTcpBoost();
        ikCTcpBoost(std::shared_ptr<boost::asio::io_service> pIOService, std::shared_ptr<tcp::acceptor>);
        ikCTcpBoost(std::shared_ptr<boost::asio::io_service> pIOService);
        ikCTcpBoost(std::shared_ptr<tcp::acceptor>);
        //ikCTcpBoost(ikCTcpBoost& tcpBoost);
        ~ikCTcpBoost();
        void Initialize(unsigned int nRecvPort);
        void SetDestinationAddress(const char* IpAddress, unsigned int nSentPort);
        bool Accept();
        bool AsyncAccept(AsyncHandler endHandler);
        bool ConnectToServer();
        bool AsyncConnectToServer(AsyncHandler endHandler);
        void Close();
        size_t SyncWrite(void* pBuffer, size_t nDataSize);
        size_t AsyncWrite(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);
        size_t SyncRead(void* pBuffer, size_t nDataSize);
        size_t AsyncRead(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);
        
        std::shared_ptr<boost::asio::io_service> m_pIOService;
        std::shared_ptr<tcp::acceptor> m_pAcceptor;
        
        void Run();

    protected:
        void handle_receive(const boost::system::error_code& error, std::size_t bytes_transferred);
        void handle_send(const boost::system::error_code& error, std::size_t bytes_transferred);
        void handle_connect(const boost::system::error_code& error);
        void handle_accept(const boost::system::error_code& error);

        AsyncHandler m_receiveHandler;
        AsyncHandler m_sendHandler;
        AsyncHandler m_connHandler;
        AsyncHandler m_acceptHandler;

        void _init();
        bool isRun;

    private:
        std::shared_ptr<tcp::socket> m_pSocket;
        std::shared_ptr<tcp::endpoint> m_pRemoteEndPoint;
        //std::shared_ptr<tcp::iostream> m_pSocketStream;
    };

}
}

#endif // __INKLUDE_C_UDP_BOOST_H__


